# -*- coding: utf-8 -*-
# 操作内容：
# @Software: PyCharm
# @File: keywords_run.py
# @Author: 一碗好酒（张智）
# @E-mail: 1473658931@qq.com, 
# @Time: 7月 21, 2021
# ---
import  re
#调用request库，发起请求，获取响应，做断言，
import pytest

from common import encry_decry
from common.dbutil import DB
from keywords.keywords_util import get_cases_infos, globals_variables


def run(client,casename):
    '''

    :param client: RequestClient对象
    :param casename:
    :return:
    '''
    cases_info = get_cases_infos(casename)
    steps = cases_info[casename]
    for step in steps:
        # url 0, method 1,headers 索引值2，请求参数 索引值3，
        #响应提取 4，状态码断言 5，响应断言 6，数据库断言  7，用例参数 8
        # 字符串转换成字典的方法：'{"params":{\n"sku_id":891,\n"num":2\n}}'
        # 1.eval():可以将类似字典的字符串转换成字典 2.json.loads() 把json字符串转换成字典
        # eval()特点: 转换空字符串会报错，所以判空
        ####请求参数的处理#######
        url = step[0]
        client.url = regex_sub(url)  #替换成访问的url
        #method
        method = step[1]
        client.method = method
        #header
        headers = step[2]
        if headers !='':  #之前是“”
            #正则表达式对字符串做处理
            client.headers = eval(regex_sub(headers))  #之前是header
        # 请求参数
        # 优先级，测试用例中有用例参数就用用例参数，否则就用默认参数
        if step[8]!='':
            params = regex_sub(step[8])# 变量为空
        else:# 就用api中的默认参数
            params = regex_sub(step[3])
        #md5函数替换
        params = regex_func(params)
        #把字符串转换为字典
        params = eval(params)
        #判断请求参数是什么类型：查询按时，data参数，file
        if 'params' in params:
            client.params = params['params']
        if 'data'  in params:
            client.data = params['data']
        if 'files' in params:
            client.files = params['files']
        if 'json' in params:
            client.json = params['json']
        #发起请求
        resp = client.send()
        # 断言提取判断

        # 数据提取
        extract_data = step[4]
        if extract_data !='':
            extract_data = eval(extract_data)
            for item in  extract_data.items():
                key = item[0]
                jsonpath_value = item[1]
                # 解析jsonpath
                value = client.extract_expr(jsonpath_value)
                #把响应数据里面提取出来的变量和值存储到全局变量global_variables
                globals_variables[key] = value

        # 状态码断言
        expect_status_code = step[5]
        # if expect_status_code !='':
        if expect_status_code != '':
            # pytest.assume(resp.status_code == expect_status_code)
            pytest.assume(resp.status_code == expect_status_code)



        #响应断言
        expect_body_assert = step[6]
        if expect_body_assert != '':
            expect_body_assert = eval(expect_body_assert)
            jsonpath_value = expect_body_assert['actual']
            actual_value = client.extract_expr(jsonpath_value)
            expect_value = expect_body_assert['expect']
            pytest.assume(actual_value==expect_value)

        #数据库断言 实际结果==预期结果
        db_assert=step[7]
        if db_assert !='':
            db_assert = eval(db_assert)
            sql = db_assert['sql']
            actual = db_assert['actual']
            expect = db_assert['expect']
            #创建数据库对象--选择关键字自己封装的数据库
            db = DB('test')
            result = db.select(sql)[0]
            actual_li = actual.split(',')
            for actual_key in actual_li:
                #获取result数据库里面的值
                actual_value = result.get(actual_key)
                expect_jsonpath = expect.get(actual_key)
                expect_value = client.extract_expr(expect_jsonpath)
                #断言
                pytest.assume(actual_value == expect_value)






#替换变量
def regex_sub(string ):
    '''

    :param string:
    :return:
    '''
    # re.findall(pattern,string)
    # pattern 正则表达式的规则  目标字符串
    # 在string这个字符串中进行检索，看是否有符合pattern正则表达式的部分，如果有就返回，没有即返回None
    # findall如果有值的话，返回的是[符合规则的值，xxx]
    # $ 以什么结尾是特殊的正则表达式，匹配的${} 这个$并没有特殊函数 \转义的意思
    # results = re.findall(r'\$\{(.+?)\}',"${{md5(yaoyao123456)}}")
    results = re.findall(r'\$\{([^\{].+?)\}', string)

    # print(results)
    for result in results:
        # buyerHost这个变量所代表的真实的值是什么？
        # global_variables里面去找
        value = globals_variables[result]
        # print('value的值是{}'.format(value))
        # 做替换${buyerHost}-'http://www.mtxshop.com:7002'
        # pattern:这个规则可以把你想要替换掉的内容匹配出来
        # string = re.sub(r'\$\{' + result + '\}', value, string)
        string = re.sub(r'\$\{' + result + r'\}', value, string)

    return string



#md5方法的替换
#方法替换的前提，方法是定义好的，
def regex_func(func_str):
    # ${{函数的名字}}
    # 1 正则表达检索哪个字符串用到了函数引用
    results =re.findall(r'\$\{\{(.+?)\((.+?)\)\}\}',func_str)
    # print(results)  # [('md5', 'yaoyao123456')]
    for result in results:
        func_name = result[0]
        # print(func_name)
        param_name = result[1]
        # print(param_name)
        # 判断文件里面是否有func_name这个函数
        if hasattr(encry_decry,func_name):
            # 获取func_name这个函数的对象
            func_obj = getattr(encry_decry,func_name)
            # 函数的调用，并获取返回值
            value = func_obj(param_name)
            # 替换变量
            # ${{md5(yaoyao123456)}} 替换成value  "${{md5(yaoyao123456)}}"
            # ${{ +func_name + ( + param_name+ )}}
            # sub(pattern,字符串的替换数据,原来的字符串)
            func_str = re.sub(r'\$\{\{'+func_name+r'\('+param_name+r'\)\}\}',str(value),func_str)
    return func_str


if __name__ == '__main__':
    # results = re.findall(r'\$\{(.+?)\}','${buyerHost}/passport/login')
    # print(results)
    global_variables= {'buyerHost': 'http://www.mtxshop.com:7002',
                       'sellerHost': 'http://www.mtxshop.com:7003',
                        'managerHost': 'http://www.mtxshop.com:7004',
                       'basicHost': 'http://www.mtxshop.com:7000',
                       'dbip': '121.42.15.146',
                        'dbport': 3306, 'dbusername': 'root', 'dbpwd': 'Testfan#123', '': ''}

    # for result in results:
    # # buyerhost这个变量所代表的真实的值
    #     value = global_variables[result]
    #     print('value{}'.format(value))
    #     # 替换${buyerhost}-'http://www.mtxshop.com:7002'
    #     string = re.sub(r'\$\{'+result+'\}',value,string)
    #     print(string)
    # return string
    # get_global_variables
    url = regex_sub('${buyerHost}/passport/login')
    print(url)